package com.amphiprion.prototype;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;

import com.amphiprion.prototype.component.GameComponent;
import com.amphiprion.prototype.control.ControlerState;
import com.amphiprion.prototype.util.BitmapUtil;

public abstract class GameScreen {
	private Context context;
	protected GameView view;
	private ScreenProperty screenProperty = new ScreenProperty();
	protected static Paint paint = new Paint();
	private List<GameComponent> components;
	private List<DelayedRun> delayedRuns;

	public GameScreen(Context context) {
		this.context = context;
		components = new ArrayList<GameComponent>();
		delayedRuns = new ArrayList<GameScreen.DelayedRun>();
	}

	protected void addComponent(GameComponent cmp) {
		cmp.activate();
		components.add(cmp);
	}

	protected void addComponent(GameComponent cmp, GameComponent before) {
		cmp.activate();
		int i = components.indexOf(before);
		if (i != 0) {
			components.add(i, cmp);
		} else {
			components.add(cmp);
		}
	}

	protected GameComponent getComponent(int index) {
		return components.get(index);
	}

	protected void removeComponent(int index) {
		GameComponent cmp = components.remove(index);
		cmp.desactivate();
	}

	protected void removeComponent(GameComponent cmp) {
		components.remove(cmp);
		cmp.desactivate();
	}

	protected void clearComponents() {
		for (GameComponent cmp : components) {
			cmp.desactivate();
		}
		components.clear();
	}

	public Context getContext() {
		return context;
	}

	public void onInput(ControlerState state, long elpased) {
		List<GameComponent> clones = new ArrayList<GameComponent>(components);
		for (int i = clones.size() - 1; i >= 0; i--) {
			GameComponent cmp = clones.get(i);
			cmp.onInput(state, elpased);
			if (cmp.isMustBeRemoved()) {
				removeComponent(cmp);
			}
		}

		// delayed
		for (int i = delayedRuns.size() - 1; i >= 0; i--) {
			DelayedRun dr = delayedRuns.get(i);
			dr.delayed -= elpased;
			if (dr.delayed <= 0) {
				delayedRuns.remove(i);
				dr.runnable.run();
			}
		}
	}

	protected abstract float getReferenceWidth();

	protected abstract float getReferenceHeight();

	protected abstract boolean isLandscape();

	protected final void onDraw(Canvas canvas) {
		screenProperty.realWidth = canvas.getWidth();
		screenProperty.realHeight = canvas.getHeight();
		screenProperty.screenScale = BitmapUtil.getScreenScale();

		if (canvas.getWidth() < canvas.getHeight()) {
			if (isLandscape()) {
				screenProperty.screenRotation = 90;
				// screenProperty.screenScale = Math.max(canvas.getWidth()
				// / getReferenceHeight(), canvas.getHeight()
				// / getReferenceWidth());
			} else {
				// screenProperty.screenScale = Math.max(canvas.getWidth()
				// / getReferenceWidth(), canvas.getHeight()
				// / getReferenceHeight());
				screenProperty.screenRotation = 0;
			}
		} else {
			if (isLandscape()) {
				// screenProperty.screenScale = Math.max(canvas.getWidth()
				// / getReferenceWidth(), canvas.getHeight()
				// / getReferenceHeight());
				screenProperty.screenRotation = 0;
			} else {
				screenProperty.screenRotation = 90;
				// screenProperty.screenScale = Math.max(canvas.getWidth()
				// / getReferenceHeight(), canvas.getHeight()
				// / getReferenceWidth());
			}
		}

		onPreDraw(canvas);
		for (GameComponent cmp : components) {
			cmp.onDraw(canvas, screenProperty);
		}
		onPostDraw(canvas);

	}

	/**
	 * Called before painting the game components.
	 * 
	 * @param canvas
	 */
	protected abstract void onPreDraw(Canvas canvas);

	/**
	 * Called after painting the game components.
	 * 
	 * @param canvas
	 */
	protected abstract void onPostDraw(Canvas canvas);

	public Resources getResources() {
		return context.getResources();
	}

	public String getString(int resId) {
		return context.getString(resId);
	}

	public String getString(int resId, Object... args) {
		return context.getString(resId, args);
	}

	public String[] getStringArray(int resId) {
		return context.getResources().getStringArray(resId);
	}

	public int getWidth() {
		return view.getWidth();
	}

	public int getHeight() {
		return view.getHeight();
	}

	public void setView(GameView view) {
		this.view = view;
	}

	public void activate() {
		for (GameComponent cmp : components) {
			cmp.activate();
		}
	}

	public void desactivate() {
		for (GameComponent cmp : components) {
			cmp.desactivate();
		}
	}

	protected void drawImage(Canvas canvas, Bitmap img, float centerX, float centerY, float scale) {
		drawImage(canvas, img, centerX, centerY, scale, paint);
	}

	protected void drawImage(Canvas canvas, Bitmap img, float centerX, float centerY, float scale, Paint paint) {
		Matrix m = new Matrix();
		m.postTranslate(-img.getWidth() / 2, -img.getHeight() / 2);
		m.postRotate(screenProperty.screenRotation);
		m.postScale(scale * screenProperty.screenScale, scale * screenProperty.screenScale);

		if (screenProperty.screenRotation == 0) {
			m.postTranslate(centerX * screenProperty.screenScale, centerY * screenProperty.screenScale);
		} else {
			m.postTranslate(canvas.getWidth() - centerY * screenProperty.screenScale, centerX * screenProperty.screenScale);
		}
		canvas.drawBitmap(img, m, paint);
	}

	protected void drawText(Canvas canvas, String str, float x, float y, Paint paint) {
		float pSize = paint.getTextSize();
		paint.setTextSize(pSize * screenProperty.screenScale);
		Matrix m = new Matrix();
		// m.postTranslate(-canvas.getWidth() / 2, -canvas.getHeight() / 2);
		m.postRotate(screenProperty.screenRotation);
		if (screenProperty.screenRotation == 0) {
			// m.postTranslate(canvas.getWidth() / 2, canvas.getHeight() / 2);
		} else {
			m.postTranslate(canvas.getWidth(), 0);
		}
		float txtX;
		float txtY;
		if (screenProperty.screenRotation == 0) {
			txtX = x * screenProperty.screenScale;
			txtY = y * screenProperty.screenScale;
		} else {
			txtX = x * screenProperty.screenScale;
			txtY = y * screenProperty.screenScale;
		}

		canvas.save();
		canvas.setMatrix(m);
		canvas.drawText(str, txtX, txtY, paint);
		// canvas.drawRect(0, 0, 400, 240, paint);
		canvas.restore();
		paint.setTextSize(pSize);
	}

	protected void drawFillRect(Canvas canvas, float left, float top, float right, float bottom, Paint paint) {
		paint.setStyle(Style.FILL);

		Matrix m = new Matrix();
		// m.postTranslate(-canvas.getWidth() / 2, -canvas.getHeight() / 2);
		m.postRotate(screenProperty.screenRotation);
		if (screenProperty.screenRotation == 0) {
			// m.postTranslate(canvas.getWidth() / 2, canvas.getHeight() / 2);
		} else {
			m.postTranslate(canvas.getWidth(), 0);
		}
		canvas.save();
		canvas.setMatrix(m);
		canvas.drawRect(left * screenProperty.screenScale, top * screenProperty.screenScale, right * screenProperty.screenScale, bottom * screenProperty.screenScale, paint);
		canvas.restore();

	}

	public ScreenProperty getScreenProperty() {
		return screenProperty;
	}

	public boolean onBackRequested() {
		return false;
	}

	public boolean isLayered() {
		return false;
	}

	public void postDelayed(Runnable r, long delayed) {
		DelayedRun d = new DelayedRun();
		d.delayed = delayed;
		d.runnable = r;
		delayedRuns.add(d);
	}

	private class DelayedRun {
		private long delayed;
		private Runnable runnable;
	}
}
